<?php
/**
 *  @brief Xử lý liên quan đến bài viết
 *  
 *  @post_status:
 *  	0: tin nháp
 *  	1: đã đăng - đang chạy
 *  	2: tin chờ duyệt
 *  	3: tin chờ đăng
 *  	4: tin trả lại khi duyệt
 *  	5: tin trả lại khi đăng
 *  	6: tin bị gỡ xuống
 *  	7: tin bị xóa
 *  	8: tin tạo mới (Khi user tạo tin mới thì sẽ lưu thành tin này để có post id sử dụng 		cho các mục đích khác)
 *
 *  @post_type
 *  	1: tin bài viết
 *  	2: tin hình ảnh
 *  	3: tin videos
 *  	4: tin audio
 */
if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class Post_m extends Base_model {
	
	public $primary_key = 'post_id';
	public function __construct()
	{
		parent::__construct();
	}
	
	function loadmeta() {
		$this->load->model("meta_m", "postmeta");
		$this->postmeta->_get_meta_table("post");
	}
	
	public function get_post( $id = 0 ) {
		return $this->get($id);
	}
	
	/*
		Trả về danh sách các bài viết đủ điều kiện chạy ở trang chủ
		
	*/
	function get_deploy_posts($args = array()) {

		//chỉ lấy các bài đã được duyệt
		$args['post_status'] = 1;
		$this->where('post_time_start <', time());
		return $this->get_posts($args);
	}

	function get_posts($args = array()) {
		$default = array(
			'posts_per_page'   => 10,
			'offset'           => 0,
			'category'         => '',
			'tax_query'         => array(),
			'event'			   => '',
			'tag'			   => '',
			'orderby'          => 'posts.post_id',
			'order'            => 'DESC',
			'include'          => '',
			'exclude'          => '',
			'meta_key'         => '',
			'meta_value'       => '',
			'post_type'        => array(0,1,2,3,4), // 1 is post, image, video, audio
			'post_status'      => FALSE,
			'search'			=> ''
			);
		
		$r = array_merge_key($args, $default);
		
		if ( ! empty($r['include']) ) {
			$incposts = explode(',', $r['include'] );
			$r['posts_per_page'] = count($incposts);  // only the number of posts included
			$this->where_in('posts.' . $this->primary_key, $incposts);
		} elseif ( ! empty($r['exclude']) )
			$this->where_not_in('posts.' . $this->primary_key, explode(',', $r['exclude'] ));
		

		if ( ! empty($r['category']) ){
			$this->join('term_posts', 'term_posts.post_id = posts.post_id');
			if(is_array($r['category']))
			{
				$this->where('(cat_id in ('.implode(", ", $r['category']).') or term_id in ('.implode(", ", $r['category']).'))');
			}
			else
			{
				$this->where("(cat_id = ".$r['category']." or term_id = ".$r['category'].")");
			}
		}

		if ( ! empty($r['event']) ){
			$this->join('term_posts', 'term_posts.post_id = posts.post_id');
			if(is_array($r['event']))
				$this->where_in('term_id', $r['event']);
			else
				$this->where('term_id', $r['event']);
		}

		if ( ! empty($r['tag']) ){
			$this->join('term_posts', 'term_posts.post_id = posts.post_id');
			if(is_array($r['tag']))
				$this->where_in('term_id', $r['tag']);
			else
				$this->where('term_id', $r['tag']);
		}

		if($r['post_status'] !== FALSE)
		{
			if(is_array($r['post_status']))
				$this->where_in('post_status', $r['post_status']);
			else
				$this->where('post_status', $r['post_status']);
		}
		
		if(is_array($r['post_type']))
			$this->where_in('post_type', $r['post_type']);
		else
			$this->where('post_type', $r['post_type']);
		
		if(!empty($r['meta_key']) || !empty($r['meta_value']))
			$this->join('postmeta', 'postmeta.post_id = posts.post_id');

		if( !empty($r['meta_key']) ) {
			if(is_array($r['meta_key']))
				$this->where_in('meta_key', $r['meta_key']);
			else
				$this->where('meta_key', $r['meta_key']);
		}
		
		if( !empty($r['meta_value']) ) {
			if(is_array($r['meta_value']))
				$this->where_in('meta_value', $r['meta_value']);
			else
				$this->where('meta_value', $r['meta_value']);
		}	

		if(!empty($r['search'])) {
			$this->like('post_title', $r['search']);
		}

		$this->order_by($r['orderby'], $r['order']);
		$this->limit($r['posts_per_page'], $r['offset']);
		return $this->get_many_by();
	}

	/*
		- Trả về thông tin của post theo status, nếu $type =='' thì trả về array, ngược lại trả về string.
		- Nếu muốn lấy thông tin permission thì theo cú pháp: ($status, 'permission_create');
		- $type: permission_create, permission_delete,permission_edit,permission_view
	*/
	function get_info_status($status, $type ='')
	{
		//Định nghĩa post status
		$post_status = array(
			0 => array('theme'=>'/index',
				'title' => 'Tin nháp',
				'permission' =>array(
						'create' =>'Posts.Draft.Create',
						'delete' =>'Posts.Draft.Delete',
						'edit' =>'Posts.Draft.Edit',
						'view' =>'Posts.Draft.View'
					)
			),//'Tin nháp',
			1 => array('theme'=>'/index',
				'title' =>'Tin đã đăng',
				'permission' =>array(
						'create' =>'Posts.Publish.Create',
						'delete' =>'Posts.Publish.Delete',
						'edit' =>'Posts.Publish.Edit',
						'view' =>'Posts.Publish.View'
					)
			),//'Tin đã đăng',

			2 => array('theme'=>'/index',
				'title' =>'Tin chờ duyệt',
				'permission' =>array(
						'create' =>'Posts.ApprovalWaiting.Create',
						'delete' =>'Posts.ApprovalWaiting.Delete',
						'edit' =>'Posts.ApprovalWaiting.Edit',
						'view' =>'Posts.ApprovalWaiting.View'
					)
				),//'Tin chờ duyệt',

			3 => array('theme'=>'/index',
				'title' =>'Tin chờ đăng',
				'permission' =>array(
						'create' =>'Posts.DeployWaiting.Create',
						'delete' =>'Posts.DeployWaiting.Delete',
						'edit' =>'Posts.DeployWaiting.Edit',
						'view' =>'Posts.DeployWaiting.View'
					)
			),//'Tin chờ đăng',
			4 => array('theme'=>'/index',
				'title' =>'Tin trả lại khi duyệt',
				'permission' =>array(
						'create' =>'Posts.SubmitReturn.Create',
						'delete' =>'Posts.SubmitReturn.Delete',
						'edit' =>'Posts.SubmitReturn.Edit',
						'view' =>'Posts.SubmitReturn.View'
					)
				),//'Tin trả lại khi duyệt',

			5 => array('theme'=>'/index',
				'title' =>'Tin trả lại khi đăng',
				'permission' =>array(
						'create' =>'Posts.ApprovalReturn.Create',
						'delete' =>'Posts.ApprovalReturn.Delete',
						'edit' =>'Posts.ApprovalReturn.Edit',
						'view' =>'Posts.ApprovalReturn.View'
					)
				),//'Tin trả lại khi đăng',

			6 => array('theme'=>'/index',
				'title' =>'Tin bị gỡ xuống',
				'permission' =>array(
						'create' =>'Posts.DisContinued.Create',
						'delete' =>'Posts.DisContinued.Delete',
						'edit' =>'Posts.DisContinued.Edit',
						'view' =>'Posts.DisContinued.View'
					)
				),//'Tin bị gỡ xuống',

			7 => array('theme'=>'/index',
				'title' =>'Tin bị xóa',
				'permission' =>array(
						'create' =>'Posts.Deleted.Create',
						'delete' =>'Posts.Deleted.Delete',
						'edit' =>'Posts.Deleted.Edit',
						'view' =>'Posts.Deleted.View'
					)
				),//'Tin bị xóa',
			8 => array('theme'=>'/index',
				'title' =>'Tạo tin mới',
				'permission' =>array(
						'create' =>'Posts.Create',
						'delete' =>'Posts.Create',
						'edit' =>'Posts.Create',
						'view' =>'Posts.Create'
					)
				),//

		);
		if(isset($post_status[$status]))
		{
			if(isset($post_status[$status][$type]))
			{
				return $post_status[$status][$type];
			}
			if(strpos($type, 'permission_') !== FALSE)
			{
				$exp = explode("_", $type);
				if(isset($post_status[$status][$exp[0]][$exp[1]]))
				{
					return $post_status[$status][$exp[0]][$exp[1]];
				}
			}
			return $post_status[$status];
		}
		return FALSE;
	}

	function num($args = array()){
		$default = array(
			'offset'           => 0,
			'category'         => '',
			'tag'			   => '',
			'orderby'          => 'post_date',
			'order'            => 'DESC',
			'include'          => '',
			'exclude'          => '',
			'meta_key'         => '',
			'meta_value'       => '',
			'post_type'        => array(0,1,2,3,4), // 1 is post, image, video, audio
			'post_status'      => FALSE,
			'search'			=> ''
			);
		
		$r = array_merge_key($args, $default);
		
		if ( ! empty($r['include']) ) {
			$incposts = explode(',', $r['include'] );
			$r['posts_per_page'] = count($incposts);  // only the number of posts included
			$this->where_in($this->primary_key, $incposts);
		} elseif ( ! empty($r['exclude']) )
			$this->where_not_in($this->primary_key, explode(',', $r['exclude'] ));
			
		if ( ! empty($r['category']) ){
			$this->join('term_posts', 'term_posts.post_id = posts.post_id');
			if(is_array($r['category']))
			{
				$this->where('(cat_id in ('.implode(", ", $r['category']).') or term_id in ('.implode(", ", $r['category']).'))');
			}
			else
			{
				$this->where("(cat_id = ".$r['category']." or term_id = ".$r['category'].")");
			}
		}

		if ( ! empty($r['tag']) ){
			$this->join('term_posts', 'term_posts.post_id = posts.post_id');
			if(is_array($r['tag']))
				$this->where_in('term_id', $r['tag']);
			else
				$this->where('term_id', $r['tag']);
		}
		
		if($r['post_status'] !== FALSE)
		{
			if(is_array($r['post_status']))
				$this->where_in('post_status', $r['post_status']);
			else
				$this->where('post_status', $r['post_status']);
		}
		
		if(is_array($r['post_type']))
			$this->where_in('post_type', $r['post_type']);
		else
			$this->where('post_type', $r['post_type']);
		
		if( !empty($r['meta_key']) ) {
			$this->join('postmeta', 'postmeta.post_id = posts.post_id');
			if(is_array($r['meta_key']))
				$this->where_in('meta_key', $r['meta_key']);
			else
				$this->where('meta_key', $r['meta_key']);
		}		

		if(!empty($r['search'])) {
			$this->like('post_title', $r['search']);
		}
		
		if( !empty($r['meta_value']) ) {
			$this->join('postmeta', 'postmeta.post_id = posts.post_id');
			if(is_array($r['meta_value']))
				$this->where_in('meta_value', $r['meta_value']);
			else
				$this->where('meta_value', $r['meta_value']);
		}
		return $this->count_by();
	}
	
	//
	// Post meta functions
	//
	
	/**
	 * Add meta data field to a post.
	 *
	 * Post meta data is called "Custom Fields" on the Administration Screen.
	 *
	 * @since 1.0
	 *
	 * @param int    $post_id    Post ID.
	 * @param string $meta_key   Metadata name.
	 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
	 * @param bool   $unique     Optional. Whether the same key should not be added.
	 *                           Default false.
	 * @return int|bool Meta ID on success, false on failure.
	 */
	function add_post_meta( $post_id = 0, $meta_key = '', $meta_value = '', $unique = false ) {
		$this->loadmeta();
		return $this->postmeta->add_metadata('post', $post_id, $meta_key, $meta_value, $unique);
	}
	
	/**
	 * Remove metadata matching criteria from a post.
	 *
	 * You can match based on the key, or key and value. Removing based on key and
	 * value, will keep from removing duplicate metadata with the same key. It also
	 * allows removing all metadata matching key, if needed.
	 *
	 * @since 1.0
	 *
	 * @param int    $post_id    Post ID.
	 * @param string $meta_key   Metadata name.
	 * @param mixed  $meta_value Optional. Metadata value. Must be serializable if
	 *                           non-scalar. Default empty.
	 * @return bool True on success, false on failure.
	 */
	function delete_post_meta( $post_id = 0, $meta_key = '', $meta_value = '' ) {
	    $this->loadmeta();
		return $this->postmeta->delete_metadata('post', $post_id, $meta_key, $meta_value);
	}
	
	/**
	 * Retrieve post meta field for a post.
	 *
	 * @since 1.0
	 *
	 * @param int    $post_id Post ID.
	 * @param string $key     Optional. The meta key to retrieve. By default, returns
	 *                        data for all keys. Default empty.
	 * @param bool   $single  Optional. Whether to return a single value. Default false.
	 * @return mixed Will be an array if $single is false. Will be value of meta data
	 *               field if $single is true.
	 */
	function get_post_meta( $post_id = 0, $key = '', $single = false ) {
		$this->loadmeta();
		return $this->postmeta->get_metadata('post', $post_id, $key, $single);
	}
	
	/**
	 * Update post meta field based on post ID.
	 *
	 * Use the $prev_value parameter to differentiate between meta fields with the
	 * same key and post ID.
	 *
	 * If the meta field for the post does not exist, it will be added.
	 *
	 * @since 1.0
	 *
	 * @param int    $post_id    Post ID.
	 * @param string $meta_key   Metadata key.
	 * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
	 * @param mixed  $prev_value Optional. Previous value to check before removing.
	 *                           Default empty.
	 * @return int|bool Meta ID if the key didn't exist, true on successful update,
	 *                  false on failure.
	 */
	function update_post_meta( $post_id, $meta_key = '', $meta_value = '', $prev_value = '' ) {	
	    $this->loadmeta();
		return $this->postmeta->update_metadata('post', $post_id, $meta_key, $meta_value, $prev_value);
	}
	
	/**
	 * Delete everything from post meta matching meta key.
	 *
	 *
	 * @param string $post_meta_key Key to search for when deleting.
	 * @return bool Whether the post meta key was deleted from the database.
	 */
	function delete_post_meta_by_key( $post_meta_key ) {
	    $this->loadmeta();
		return $this->postmeta->delete_metadata( 'post', null, $post_meta_key, '', true );
	}

	/*
		Xử lý object post trước khi hiển thị ra ngoài
	*/
	function process_post_item($post)
	{
		$post->url = post_url($post);
		$post->post_title = html_encode($post->post_title);
		return $post;
	}

	/*
		Init các câu quyery theo post status
	*/
	function condition_query_post_status($post_status = 0)
	{
		if($this->get_info_status($post_status) != FALSE)
		{
			switch ($post_status) {
				case 0:
				case 4:
				case 5:
				case 6:
					$this->where('admin_id', $this->admin->id);
				break;
				case 1:
				case 2:
				case 3:
				case 7:
					
				break;
				case 8:
					//$this->only_deleted();
				break;

				default:
					# code...
					break;
			}
			$this->where('post_status',$post_status);
			return $this;
		}
		return $this;
	}

	/*
		- Return new status of post
		- $type: up, down

	*/
	function get_post_status_change($post_status, $type = 'up')
	{
		switch ($post_status) {
			case 0:
				$status_up = 2;
				$status_down = 0;
			break;
			case 1:
				$status_up = 1;
				$status_down = 6;
			break;
			case 2:
				$status_down = 4;
				$status_up = 3;
				break;
			case 3:
				$status_down = 5;
				$status_up = 1;
				break;
			case 4:
				$status_down = 0;
				$status_up = 2;
				break;

			case 5:
				$status_down = 0;
				$status_up = 2;
				break;
			case 6:
				$status_down = 0;
				$status_up = 2;
				break;

			case 7:
				$status_down = 0;
				$status_up = 2;
				break;
			
			
			default:
				$status_down = 0;
				$status_up = 0;
				break;
		}
		if($type =='up') return $status_up;
		return $status_down;
	}

	//Kiểm tra quyền khi post bài
	function post_edit_check_permission($post, $edit_id = 0)
	{

		if(!isset($post) && $edit_id) 
		{
			$this->messages->add('Bài viết không tồn tại','error');
			return FALSE;
		};
		if(!is_object($post)) $post = (object)$post;

		if($edit_id >0 )
		{
			//kiểm tra lock
			$lock = $this->metapost_edit_lock($post->post_id, 'get');
			if($lock && $lock->locktime > 0 && $lock->admin_account != $this->admin->account)
			{
				$this->messages->add('Bài viết đang bị sửa bởi <b>'.$lock->admin_account.'</b>','error');
				return FALSE;
			}
			$permission_edit = $this->get_info_status($post->post_status, 'permission_edit');
			if(!has_permission($permission_edit))
			{
				$this->messages->add('Bạn không có quyền vào phần này.','error');
				return FALSE;
			}
		}
		else
		{
			//Kiểm tra quyền tạo bài viết
			if(!has_permission('Posts.Create'))
			{
				// $this->messages->add('Bạn không có quyền vào phần này.','error');
				return FALSE;
			}
		}
		return TRUE;
	}

	/*
		@Meta: _cms_post_edit_lock
		@Khóa bài viết, nếu bài viết đang bị khóa thì sẽ không thể chỉnh sửa được, ngoại trừ người đang chỉnh sửa

		$post_id:			post id
		$admin_account:		admin account, if false then current admin account login
		$type:				+ 'get' -> Trả về thông tin trạng thái lock của bài viết đó
							+ 'set_lock' -> lock bài viết này
							+ 'set_unlock' -> unlock bài viết này
		$set_lock_time:		time lock
	
	*/
	function metapost_edit_lock($post_id, $type = 'get', $admin_account = FALSE)
	{
		if(!$post_id || $post_id <0) return FALSE;
		if(!$admin_account) 
			$admin_account = $this->admin->account;

		$meta_time_key = '_cms_post_edit_lock_time';
		$meta_account_key = '_cms_post_edit_lock_byaccount';
		$result = new stdClass();
		$result->locktime = 0;
		$result->admin_account = '';
		if($type == 'get')
		{
			$result->locktime = $this->get_post_meta($post_id, $meta_time_key, true);
			$result->admin_account = $this->get_post_meta($post_id, $meta_account_key, true);

			//if thời gian lock quá hạn thì unlock bài viết
			if($result->locktime > 0 
				&& $this->config->item('cms_admin_post_locktime') >0  
				&& $result->locktime < time() - $this->config->item('cms_admin_post_locktime') * 60)
			{
				return $this->metapost_edit_lock($post_id, 'set_unlock');
			}
			return $result;
		}
		else if($type == 'set_lock')
		{
			$result->locktime = time();
			$result->admin_account = $admin_account;
			$this->update_post_meta($post_id, $meta_time_key, $result->locktime);
			$this->update_post_meta($post_id, $meta_account_key, $result->admin_account);
			return $result;
		}
		else if($type == 'set_unlock')
		{
			$result->locktime = 0;
			$result->admin_account = $admin_account;
			$this->update_post_meta($post_id, $meta_time_key, $result->locktime);
			$this->update_post_meta($post_id, $meta_account_key, $result->admin_account);
			return $result;
		}
		else
		{
			return FALSE;
		}
	}

	/*
		@brief: Return class icon by post_status
		@$post_status: post status
	*/
	function get_post_status_icon($post_status)
	{
		$icon = '';
		switch ($post_status) {
			case 1:
				$icon = 'fa-check-square';
				break;
			case 1:
				$icon = 'fa-file-text-o';
				break;
			case 2:
				$icon = 'fa-tasks';
				break;
			case 3:
				$icon = 'fa-building-o';
				break;
			case 4:
			case 5:
			case 6:
				$icon = 'fa-arrow-down';
				break;
			case 7:
				$icon = 'fa-trash-o';
				break;
			
			default:
				# code...
				break;
		}
		return $icon;
	}
}